package com.yxs.go_bang.game;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yxs.go_bang.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

@Component // matcher 匹配器
public class Matcher {
    // 记得处理线程安全问题 7把锁
    private Queue<User> normalQueue =new LinkedList<>();
    private Queue<User> highQueue=new LinkedList<>();
    private Queue<User> veryHighQueue=new LinkedList<>();

    @Autowired
    private OnlineUserManaage onlineUserManaage;
    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private RoomManager roomManager;

    // 操作匹配队列的方法
    // 把玩家放到匹配队列中
    public void add(User user){
        if (user.getScore()<2000){
            synchronized (normalQueue){
                normalQueue.offer(user);
                normalQueue.notify();
            }
            System.out.println("玩家："+user.getUsername()+"进入 normalqueue ！");
        } else if (user.getScore() >= 2000 && user.getScore() < 3000) {
            synchronized (highQueue){
                highQueue.offer(user);
                highQueue.notify();
            }
            System.out.println("玩家：" + user.getUsername() + "进入 highQueue ！");
        }else {
            synchronized (veryHighQueue){
                veryHighQueue.offer(user);
                veryHighQueue.notify();
            }

            System.out.println("玩家：" + user.getUsername() + "进入 veryHighQueue ！");

        }
    }

    // 点击停止匹配，把玩家从匹配队列删除
    public void remove(User user){
        if (user.getScore()<2000){
            synchronized (normalQueue){
                normalQueue.remove(user);
            }
            System.out.println("玩家："+user.getUsername()+"离开 normalqueue ！");
        } else if ( user.getScore() >= 2000 && user.getScore() < 3000) {
            synchronized (highQueue){
                highQueue.remove(user);
            }
            System.out.println("玩家：" + user.getUsername() + "离开 highQueue ！");
        }else {
            synchronized (veryHighQueue){
                veryHighQueue.remove(user);

            }
            System.out.println("玩家：" + user.getUsername() + "离开 veryHighQueue ！");

        }
    }

    public Matcher() {
        Thread t1= new Thread(() -> {
            while (true){
                handlerMatch(normalQueue);
            }
        });
        t1.start();
        Thread t2= new Thread(() -> {
            while (true){
                handlerMatch(highQueue);
            }
        });
        t2.start();
        Thread t3= new Thread(() -> {
            while (true){
                handlerMatch(veryHighQueue);
            }
        });
        t3.start();
    }

    private void handlerMatch(Queue<User> matchQueue) {
        synchronized (matchQueue){
            try {
                // 1. 检测队列中元素是否达到2个
                // 解决忙等问题： wait/notify
                // 队列的初始情况可能为空
                // 如果此时加入一个玩家到匹配队列，也是还不能进行后续操作的
                // 因此这里的检查队列元素判定不能用if 要用while循环才行

                while (matchQueue.size()<2){
                    matchQueue.wait();
                }
                // 2. 尝试从队列中取出两个元素
                User player1=matchQueue.poll();
                User player2=matchQueue.poll();
                System.out.println("匹配出两个玩家："+player1.getUsername()+"and "+player2.getUsername());
                // 3.获取到玩家的websocket会话，获取会话的目的是为了告诉玩家，你排到了
                WebSocketSession session1= onlineUserManaage.getFromGameHall(player1.getUserId());
                WebSocketSession session2=onlineUserManaage.getFromGameHall(player2.getUserId());
                // 一系列双重校验
                if (session1==null){
                    matchQueue.offer(player2);
                    return;
                }
                if (session2==null){
                    matchQueue.offer(player1);
                    return;
                }
                if (session1==session2){
                    matchQueue.offer(player1);
                    return;
                }
                // 4. 把匹配到的两个玩家放到一个游戏房间中
                Room room=new Room();
                roomManager.add(room,player1.getUserId(),player2.getUserId());


                // 5. 反馈信息给玩家，通过websocket返回一个message为matchSuccess 响应
                // 需要给两个玩家都进行反馈,需要返回两次
                MatchResponse response1=new MatchResponse();
                response1.setOk(true);
                response1.setMessage("matchSuccess");
                String json1=objectMapper.writeValueAsString(response1);
                session1.sendMessage(new TextMessage(json1));

                MatchResponse response2=new MatchResponse();
                response1.setOk(true);
                response1.setMessage("matchSuccess");
                String json2=objectMapper.writeValueAsString(response1);
                session2.sendMessage(new TextMessage(json2));


            }catch (IOException | InterruptedException e){
                e.printStackTrace();
            }

        }
    }
}
